package com.example.securitydemos.config.authentication;

/**
 * @author linjy on 2023/1/30
 * 基于自定义的认证提供器实现图形验证码
 * 在常规的数据库认证之上,添加图形验证码功能
 */

import com.example.securitydemos.exception.VerificationCodeException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 *
 */
//@Component
public class MyAuthenticationProvider extends DaoAuthenticationProvider {

    /**
     * 构造方法注入UserDetailService和PasswordEncoder
     */
    public MyAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        this.setUserDetailsService(userDetailsService);
        this.setPasswordEncoder(passwordEncoder);
    }

    /**
     * 在常规的认证之上,添加额外的图形验证码功能
     */
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException {
        //获取token令牌中关联的details对象，并将其转换为我们自定义的MyWebAuthenticationDetails
        MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) usernamePasswordAuthenticationToken.getDetails();
        String imageCode = details.getImageCode();
        String savedImageCode = details.getSavedImageCode();

        // 检验图形验证码
        if (StringUtils.isEmpty(imageCode) || StringUtils.isEmpty(savedImageCode) || !imageCode.equals(savedImageCode)) {
            throw new VerificationCodeException();
        }

        //在正常的认证检查之前，添加额外的关于图形验证码的校验
        super.additionalAuthenticationChecks(userDetails, usernamePasswordAuthenticationToken);
    }

}
